﻿namespace MicroCloud.Packs
{
    /// <summary>
    /// 系统模块基类
    /// </summary>
    public abstract class PackBase
    {
        #region 属性
        /// <summary>
        /// 获取 模块级别
        /// <para>级别越小越先启动</para>
        /// </summary>
        public virtual PackLevel Level => PackLevel.Application;

        /// <summary>
        /// 获取 模块启动顺序编号
        /// <para>模块启动的顺序先按级别启动，级别内部再按此顺序启动，级别默认为0，表示无依赖，需要在同级别有依赖顺序的时候，再重写为 >0 的顺序值。</para>
        /// </summary>
        public virtual int OrderNo => 0;
   
        /// <summary>
        /// 获取 是否已可用
        /// </summary>
        public bool IsEnabled { get; protected set; }

        /// <summary>
        /// 获取 模块类型
        /// </summary>
        public Type Type => GetType();

        /// <summary>
        /// 获取 模块描述
        /// </summary>
        public virtual string Description => Type.GetDescription(true);

        #endregion

        #region 方法
        /// <summary>
        /// 将模块服务添加到依赖注入服务容器中
        /// </summary>
        /// <param name="services">依赖注入服务容器</param>
        /// <returns>服务集合</returns>
        public virtual IServiceCollection AddServices(IServiceCollection services)
        {
            return services;
        }

        /// <summary>
        /// 应用模块服务
        /// </summary>
        /// <param name="provider">服务提供者</param>
        public virtual void UsePack(IServiceProvider provider)
        {
            IsEnabled = true;
        }

        /// <summary>
        /// 获取当前模块的依赖模块类型集合
        /// </summary>
        /// <param name="packType">当前的模块类型</param>
        /// <returns>当前模块的依赖模块类型集合</returns>
        internal Type[] GetDependPackTypes(Type packType = null)
        {
            if (packType == null)
            {
                packType = GetType();
            }
            DependsOnPacksAttribute[] dependAttrs = packType.GetAttributes<DependsOnPacksAttribute>();
            if (dependAttrs.Length == 0)
            {
                return Array.Empty<Type>();
            }

            List<Type> dependTypes = new();
            foreach (DependsOnPacksAttribute dependAttr in dependAttrs)
            {
                Type[] packTypes = dependAttr.DependedPackTypes;
                if (packTypes.Length == 0)
                {
                    continue;
                }
                dependTypes.AddRange(packTypes);
                foreach (Type type in packTypes)
                {
                    dependTypes.AddRange(GetDependPackTypes(type));
                }
            }

            return dependTypes.Distinct().ToArray();
        }

        #endregion
    }
}